#include "AudioManager.h"
#include "sfmlphysfs.hpp"
#include "DebugLog.h"

AudioManager::AudioManager(void) : _mode(RESOURCE_LOAD_FROM_ARCHIVE)
{
	_loadAudioFptr[RESOURCE_LOAD_FROM_ARCHIVE] = &AudioManager::loadSoundFromArchive;
	_loadAudioFptr[RESOURCE_LOAD_FROM_FILEPATH] = &AudioManager::loadSoundFromFile;
}

AudioManager::~AudioManager(void){}

AudioManager* AudioManager::_instance = nullptr;

AudioManager* AudioManager::getSingletonPtr()
{
	if (_instance == nullptr)
	{
		_instance = new AudioManager();
	}
	return _instance;
}

void AudioManager::cleanSingleton()
{
	if (_instance != nullptr)
	{
		delete _instance;
		_instance = nullptr;
	}
}

sf::SoundBuffer* AudioManager::loadSound(const std::string& filepath, const std::string& id)
{
	sf::SoundBuffer* sb = doesSoundExist(id);
	if (sb)
		return sb;
	return (this->*_loadAudioFptr[_mode])(filepath, id);
}

sf::SoundBuffer* AudioManager::loadSoundFromArchive(const std::string& filepath, const std::string& id)
{
	if (!PHYSFS_exists(filepath.c_str()))
	{
		Debug::log("ERROR: " + filepath + " does not exist.");
		abort();
	}

	sf::physfs stream(filepath.c_str());
	sf::SoundBuffer* sb = new sf::SoundBuffer;
	if (!sb->loadFromStream(stream))
	{
		Debug::log("ERROR: could not load " + filepath + " from stream.");
		abort();
	}
	_soundFX.insert(std::make_pair(id, sb));
	return sb;
}

sf::SoundBuffer* AudioManager::loadSoundFromFile(const std::string& filepath, const std::string& id)
{
	sf::SoundBuffer* sb = new sf::SoundBuffer;
	if (!sb->loadFromFile(filepath))
	{
		Debug::log("ERROR: could not load " + filepath + " from folder.");
		abort();
	}
	_soundFX.insert(std::make_pair(id, sb));
	return sb;
}

sf::SoundBuffer* AudioManager::doesSoundExist(const std::string& id)
{
	if (!_soundFX.empty())
	{
		std::map<std::string, sf::SoundBuffer*>::iterator it = _soundFX.find(id);
		if (it != _soundFX.end())
			return it->second;
	}
	return nullptr;
}

void AudioManager::setMode(int mode)
{
	if ((mode == RESOURCE_LOAD_FROM_ARCHIVE) || (mode == RESOURCE_LOAD_FROM_FILEPATH))
		_mode = mode;
}

void AudioManager::unloadSound(const std::string& id)
{
	auto it = _soundFX.find(id);
	if (it != _soundFX.end())
	{
		delete it->second;
		it->second = nullptr;
		_soundFX.erase(it);
	}
}

void AudioManager::unloadAllSounds()
{
	for (auto it = _soundFX.begin(); it != _soundFX.end(); it++)
	{
		delete it->second;
		it->second = nullptr;
	}
	_soundFX.clear();
}